return ret;
}
+unsigned long long parse_hex(char *s,char *match)
+{
+ char *s1 = strstr(s,match);
+ unsigned long long ret;
+
+ if ( s1 == NULL )
+ return 0LL;
+ s1 += 2;
+ if ( *s1++ != ':' )
+ return 0LL;
+ sscanf(s1,"%llx",&ret);
+ return ret;
+}
+
unsigned long long parse2(char *s,char *match1, char *match2)
{
char match[3];
s1 += 2;
if (*s1++ != ':')
return;
- while (*s1 <= '0' && *s1 <= '9')
+ while (*s1 >= '0' && *s1 <= '9')
*b++ = *s1++;
*b++ = ',';
s1 = strstr(s1,match);
unsigned long long flush_objs = parse(s,"ot");
parse_string(s,"PT",pool_type,2);
+ if (pool_type[1] == 'S')
+ return; /* no need to repeat print data for shared pools */
printf("domid%lu,id%lu[%s]:pgp=%llu(max=%llu) obj=%llu(%llu) "
"objnode=%llu(%llu) puts=%llu/%llu/%llu(dup=%llu/%llu) "
"gets=%llu/%llu(%llu%%) "
char pool_type[3];
char buf[BUFSIZE];
unsigned long pool_id = parse(s,"PI");
- unsigned long long uid0 = parse(s,"U0");
- unsigned long long uid1 = parse(s,"U1");
+ unsigned long long uid0 = parse_hex(s,"U0");
+ unsigned long long uid1 = parse_hex(s,"U1");
unsigned long long pgp_count = parse(s,"Pc");
unsigned long long max_pgp_count = parse(s,"Pm");
unsigned long long obj_count = parse(s,"Oc");
parse_string(s,"PT",pool_type,2);
parse_sharers(s,"SC",buf,BUFSIZE);
- printf("poolid=%lu[%s] uuid=%llu.%llu, shared-by:%s: "
+ printf("poolid=%lu[%s] uuid=%llx.%llx, shared-by:%s: "
"pgp=%llu(max=%llu) obj=%llu(%llu) "
"objnode=%llu(%llu) puts=%llu/%llu/%llu(dup=%llu/%llu) "
"gets=%llu/%llu(%llu%%) "
tmem_free(obj,sizeof(obj_t),pool);
}
-static NOINLINE void obj_rb_destroy_node(struct rb_node *node)
-{
- obj_t * obj;
-
- if ( node == NULL )
- return;
- obj_rb_destroy_node(node->rb_left);
- obj_rb_destroy_node(node->rb_right);
- obj = container_of(node, obj_t, rb_tree_node);
- tmem_spin_lock(&obj->obj_spinlock);
- ASSERT(obj->no_evict == 0);
- radix_tree_destroy(&obj->tree_root, pgp_destroy, rtn_free);
- obj_free(obj,1);
-}
-
static NOINLINE int obj_rb_insert(struct rb_root *root, obj_t *obj)
{
struct rb_node **new, *parent = NULL;
}
/* free an object after destroying any pgps in it */
-static NOINLINE void obj_destroy(obj_t *obj)
+static NOINLINE void obj_destroy(obj_t *obj, int no_rebalance)
{
ASSERT_WRITELOCK(&obj->pool->pool_rwlock);
radix_tree_destroy(&obj->tree_root, pgp_destroy, rtn_free);
- obj_free(obj,0);
-}
-
-/* destroy all objects in a pool */
-static NOINLINE void obj_rb_destroy_all(pool_t *pool)
-{
- int i;
-
- tmem_write_lock(&pool->pool_rwlock);
- for (i = 0; i < OBJ_HASH_BUCKETS; i++)
- obj_rb_destroy_node(pool->obj_rb_root[i].rb_node);
- tmem_write_unlock(&pool->pool_rwlock);
+ obj_free(obj,no_rebalance);
}
-/* destroys all objects in a pool that have last_client set to cli_id */
-static void obj_free_selective(pool_t *pool, cli_id_t cli_id)
+/* destroys all objs in a pool, or only if obj->last_client matches cli_id */
+static void pool_destroy_objs(pool_t *pool, bool_t selective, cli_id_t cli_id)
{
struct rb_node *node;
obj_t *obj;
obj = container_of(node, obj_t, rb_tree_node);
tmem_spin_lock(&obj->obj_spinlock);
node = rb_next(node);
- if ( obj->last_client == cli_id )
- obj_destroy(obj);
+ ASSERT(obj->no_evict == 0);
+ if ( !selective )
+ obj_destroy(obj,1);
+ else if ( obj->last_client == cli_id )
+ obj_destroy(obj,0);
else
tmem_spin_unlock(&obj->obj_spinlock);
}
return -1;
sl->client = new_client;
list_add_tail(&sl->share_list, &pool->share_list);
- printk("adding new %s %d to shared pool owned by %s %d\n",
- client_str, new_client->cli_id, client_str, pool->client->cli_id);
+ if ( new_client->cli_id != pool->client->cli_id )
+ printk("adding new %s %d to shared pool owned by %s %d\n",
+ client_str, new_client->cli_id, client_str, pool->client->cli_id);
return ++pool->shared_count;
}
if (new_client->pools[poolid] == pool)
break;
ASSERT(poolid != MAX_POOLS_PER_DOMAIN);
+ new_client->eph_count += _atomic_read(pool->pgp_count);
+ old_client->eph_count -= _atomic_read(pool->pgp_count);
+ list_splice_init(&old_client->ephemeral_page_list,
+ &new_client->ephemeral_page_list);
printk("reassigned shared pool from %s=%d to %s=%d pool_id=%d\n",
cli_id_str, old_client->cli_id, cli_id_str, new_client->cli_id, poolid);
pool->pool_id = poolid;
ASSERT(is_shared(pool));
ASSERT(pool->client != NULL);
- obj_free_selective(pool,cli_id);
+ ASSERT_WRITELOCK(&tmem_rwlock);
+ pool_destroy_objs(pool,1,cli_id);
list_for_each_entry(sl,&pool->share_list, share_list)
{
if (sl->client->cli_id != cli_id)
ASSERT(pool != NULL);
if ( (is_shared(pool)) && (shared_pool_quit(pool,cli_id) > 0) )
{
- printk("tmem: unshared shared pool %d from %s=%d\n",
- pool->pool_id, cli_id_str,pool->client->cli_id);
+ printk("tmem: %s=%d no longer using shared pool %d owned by %s=%d\n",
+ cli_id_str, cli_id, pool->pool_id, cli_id_str,pool->client->cli_id);
return;
}
printk("%s %s-%s tmem pool ",destroy?"destroying":"flushing",
is_persistent(pool) ? "persistent" : "ephemeral" ,
is_shared(pool) ? "shared" : "private");
printk("%s=%d pool_id=%d\n", cli_id_str,pool->client->cli_id,pool->pool_id);
- obj_rb_destroy_all(pool);
+ pool_destroy_objs(pool,0,CLI_ID_NULL);
if ( destroy )
{
pool->client->pools[pool->pool_id] = NULL;
if ( obj == NULL )
goto out;
tmem_write_lock(&pool->pool_rwlock);
- obj_destroy(obj);
+ obj_destroy(obj,0);
pool->flush_objs_found++;
tmem_write_unlock(&pool->pool_rwlock);
{
if ( shpool->uuid[0] == uuid_lo && shpool->uuid[1] == uuid_hi )
{
- printk("(matches shared pool uuid=%"PRIx64".%"PRIu64") ",
+ printk("(matches shared pool uuid=%"PRIx64".%"PRIx64") ",
uuid_hi, uuid_lo);
printk("pool_id=%d\n",d_poolid);
client->pools[d_poolid] = global_shared_pools[s_poolid];
if ( cli_id == CLI_ID_NULL )
{
list_for_each_entry(client,&global_client_list,client_list)
- {
client->frozen = freeze;
- printk("tmem: all pools %s for all %ss\n",s,client_str);
- }
+ printk("tmem: all pools %s for all %ss\n",s,client_str);
}
else
{
}
}
- if ( op.cmd == TMEM_NEW_POOL )
+ if ( op.cmd == TMEM_NEW_POOL || op.cmd == TMEM_DESTROY_POOL )
{
if ( !tmem_write_lock_set )
{